/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.createvmmetadata;

import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.formserver.viewmodel.util.ViewModelUtils;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.util.ArrayList;

/**
 * 与元数据交互的工具
 */
public class GspMetadataExchangeUtil {
    private final static String VM_TYPE = "VMComponent";
    private final static String VM_FILESUFFIX = ".vmCmp";
    private final static String VOACTIONCONTROLLER = "VOActionController";

    public static GspMetadataExchangeUtil getInstance() {
        return new GspMetadataExchangeUtil();
    }

    private GspMetadataExchangeUtil() {
    }

    /**
     * 业务实体编号
     */
    private String privateVMActionCode;

    private String getVMActionCode() {
        return privateVMActionCode;
    }

    private void setVMActionCode(String value) {
        privateVMActionCode = value;
    }

    /**
     * 元数据存放路径
     */
    private String privateMetadataPath;

    private String getMetadataPath() {
        return privateMetadataPath;
    }

    private void setMetadataPath(String value) {
        privateMetadataPath = value;
    }

    /**
     * 元数据名称
     */
    private String privateComponentName;

    private String getComponentName() {
        return privateComponentName;
    }

    private void setComponentName(String value) {
        privateComponentName = value;
    }

    /**
     * 是否是新建元数据
     */
    private boolean privateIsNewMetadata;

    private boolean getIsNewMetadata() {
        return privateIsNewMetadata;
    }

    private void setIsNewMetadata(boolean value) {
        privateIsNewMetadata = value;
    }

    private String privateBizObjectID;

    private String getBizObjectID() {
        return privateBizObjectID;
    }

    private void setBizObjectID(String value) {
        privateBizObjectID = value;
    }

    private String privateNameSpace;

    private String getNameSpace() {
        return privateNameSpace;
    }

    private void setNameSpace(String value) {
        privateNameSpace = value;
    }

    /**
     * 创建构件元数据，返回构件元数据ID
     *
     * @param component    构件实体
     * @param path         生成构件元数据的路径
     * @param vmActionCode 业务实体编号
     * @return 生成的构件元数据名称
     * <see cref="string"/>
     */
    public final String establishVMMetdadata(GspComponent component, String path, String vmActionCode, String bizObjectID, String nameSpace) {
        this.setIsNewMetadata(true);
        this.setVMActionCode(vmActionCode);
        this.setMetadataPath(path);
        this.setBizObjectID(bizObjectID);
        this.setNameSpace(nameSpace);
        //1、构建元数据实体
        GspMetadata metadata = buildGspMetadataEntity(component, false);
        //2、生成构件元数据
        return generateGspMetadata(metadata);
    }

    /**
     * 更新构件元数据
     *
     * @param component 构件实体
     * @param fullPath  要修改的构件元数据完整路径
     */
    public final void updateGspMetadata(GspComponent component, String fullPath, String bizEntityCode, String bizObjectID, String nameSpace) {
        this.setIsNewMetadata(false);
        this.setVMActionCode(bizEntityCode);
        this.setBizObjectID(bizObjectID);
        this.setNameSpace(nameSpace);
        this.setMetadataPath(ViewModelUtils.getDirectoryName(fullPath));
        this.setComponentName(ViewModelUtils.getFileNameWithoutExtension(fullPath));
        //1、构建元数据实体
        GspMetadata metadata = buildGspMetadataEntity(component, true);
        updateComponentMetadata(metadata, fullPath);
    }


    ///#region 构建构件元数据实体

    /**
     * 创建GspMetadata实体
     *
     * @param component 构件实体
     * @return GspMetadata实体
     */


    private GspMetadata buildGspMetadataEntity(GspComponent component, boolean isUpdate) {
        GspMetadata metadata = createMetadataEntity();

        evaluateMetadataHeader(component, metadata);
        evaluateMetadataContent(component, metadata);
        return metadata;
    }

    /**
     * 创建元数据实例
     *
     * @return 实例化的元数据
     * <see cref="GspMetadata"/>
     */
    private GspMetadata createMetadataEntity() {
        GspMetadata tempVar = new GspMetadata();
        tempVar.setHeader(new MetadataHeader());
        tempVar.setRefs(new ArrayList<>());
        tempVar.setRelativePath(this.getMetadataPath());
        return tempVar;
    }

    /**
     * 为元数据的Header属性赋值
     *
     * @param component 构件实体
     * @param metadata  元数据实体
     */
    private void evaluateMetadataHeader(GspComponent component, GspMetadata metadata) {
        if (ViewModelUtils.checkNull(metadata.getHeader().getNameSpace())) {
            metadata.getHeader().setNameSpace(getNameSpace());
        }

        metadata.getHeader().setName(generateComponentMetadataName(component, this.getMetadataPath()));
        metadata.getHeader().setCode(generateComponentMetadataName(component, this.getMetadataPath()));
        metadata.getHeader().setFileName(this.getComponentName() + VM_FILESUFFIX);
        metadata.getHeader().setType(VM_TYPE);

        if (!ViewModelUtils.checkNull(getBizObjectID())) {
            metadata.getHeader().setBizobjectID(getBizObjectID());
        }

        if (ViewModelUtils.checkNull(metadata.getHeader().getId()) && ViewModelUtils.checkNull(component.getComponentID())) //新建构件元数据时，需要初始化后获取ID
        {
            MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
            //初始化元数据，为了获取元数据ID
            metadata = metadataService.initializeMetadataEntity(metadata);
            component.setComponentID(metadata.getHeader().getId());
        } else if (ViewModelUtils.checkNull(metadata.getHeader().getId()) && !ViewModelUtils.checkNull(component.getComponentID())) //修改构件元数据时，需要为元数据的ID赋值
        {
            metadata.getHeader().setId(component.getComponentID());
        }
    }

    /**
     * 为元数据的Content属性赋值
     *
     * @param component 构件实体
     * @param metadata  元数据实体
     */
    private void evaluateMetadataContent(GspComponent component, GspMetadata metadata) {
        metadata.setContent(component);
    }

    ///#endregion

    /**
     * 生成构件元数据
     *
     * @param metadata 元数据
     * @return 生成的构件元数据名称
     * <see cref="string"/>
     */
    private String generateGspMetadata(GspMetadata metadata) {
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

        //创建元数据
        metadataService.createMetadata(this.getMetadataPath(), metadata);
        return metadata.getHeader().getCode();
    }

    private void updateComponentMetadata(GspMetadata metadata, String fullPath) {
        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

        metadataService.saveMetadata(metadata, fullPath);
//		 System.out.println("当前元数据ID" + metadata.getHeader().getId());
//		 System.out.println("当前路径为：" + fullPath);

    }

    /**
     * 生成当前路径下唯一的元数据名称
     *
     * @param component 构件实体
     * @param path      生成的元数据存放路径
     * @return 唯一的要生成的元数据名称
     */
    private String generateComponentMetadataName(GspComponent component, String path) {
        // 构件元数据命名规则
        String metadataFileName = this.getVMActionCode() + component.getComponentCode() + VOACTIONCONTROLLER;
        // 若为新增元数据操作，则需要检查路径下是否有重名元数据；若为修改元数据操作，则无需操作
        if (this.getIsNewMetadata()) {
            String orgMetadataFileName = metadataFileName;
            String metadataFileNameWithSuffix = metadataFileName + VM_FILESUFFIX;
            int index = 0;
            MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
            while (metadataService.isMetadataExist(path, metadataFileNameWithSuffix)) {
                //（同一个Be元数据中，若有重名，则自动增加后缀）
                metadataFileName = orgMetadataFileName + ++index;
                metadataFileNameWithSuffix = metadataFileName + VM_FILESUFFIX;
            }
            this.setComponentName(metadataFileName);
        }

        return metadataFileName;
    }
}